#include "simulator.h"

simulator::simulator(const S2F_config_t *config, int senderBufferSize, int receiverBufferSize) {
	sender = S2F_GenerateSender(config, senderBufferSize);
	receiver = S2F_GenerateReceiver(config, receiverBufferSize);
}

simulator::~simulator()
{
	S2F_DeleteSender(sender);
	S2F_DeleteReceiver(receiver);
}

void simulator::sim0(void)
{
	int count = 0;
	for (size_t i = 0; i < 1000; ++i) {
		vector<unsigned char> src = genData(rand() % (48000) + 1);
		unsigned char buffer[50000], recv_buffer[50000];

		S2F_SenderGenFrame(sender, (unsigned char *)src.data(), src.size());
		//logStr('c', data2Str(src.data(), src.size()));
		int len = S2F_SenderGetContext(sender, buffer, 50000);
		S2F_ReceiverAppendData(receiver, buffer, len / 2, 0);

		while (1) {
			int frame_len = S2F_ReceiverParse(receiver, recv_buffer, 50000);
			if (frame_len <= 0) {
				break;
			}
			logStr('g', data2Str(recv_buffer, frame_len));

			if (src.size() == frame_len) {
				if ((0 == memcmp(src.data(), recv_buffer, frame_len))) {
					count++;
				}
			}
		}

		S2F_ReceiverAppendData(receiver, buffer + len / 2, len - len / 2, 0);

		while (1) {
			int frame_len = S2F_ReceiverParse(receiver, recv_buffer, 50000);
			if (frame_len <= 0) {
				break;
			}
			//logStr('g', data2Str(recv_buffer, frame_len));

			if (src.size() == frame_len) {
				if ((0 == memcmp(src.data(), recv_buffer, frame_len))) {
					count++;
				}
			}
		}
	}

	cout << count << endl;
}

void simulator::sim1(void)
{
	int count = 0;
	for (size_t i = 0; i < 1000; ++i) {
		unsigned char buffer[50], recv_buffer[50];
		vector<unsigned char> src1 = genData(rand() % (5) + 1);
		vector<unsigned char> src2 = genData(rand() % (10) + 1);

		S2F_SenderGenFrame(sender, (unsigned char*)src1.data(), src1.size());
		logStr('c', data2Str(src1.data(), src1.size()));
		S2F_SenderGenFrame(sender, (unsigned char*)src2.data(), src2.size());
		logStr('c', data2Str(src2.data(), src2.size()));
		int len = S2F_SenderGetContext(sender, buffer, 50);
		S2F_ReceiverAppendData(receiver, buffer, len / 2, 0);

		while (1) {
			int frame_len = S2F_ReceiverParse(receiver, recv_buffer, 50);
			if (frame_len <= 0) {
				break;
			}
			logStr('g', data2Str(recv_buffer, frame_len));
		}

		S2F_ReceiverAppendData(receiver, buffer + len / 2, len - len / 2, 0);

		while (1) {
			int frame_len = S2F_ReceiverParse(receiver, recv_buffer, 50);
			if (frame_len <= 0) {
				break;
			}
			logStr('g', data2Str(recv_buffer, frame_len));
		}

		cout << "" << endl;
	}

	cout << count << endl;
}

//int simulator::sim1(unsigned char* send, int length, unsigned char* rec, int size)
//{
//	unsigned int sendLength;
//	unsigned int recLength;
//	unsigned char* data;
//
//	logStr('r', data2Str(send, length));
//	sendLength = S2F_SenderGenFrame(sender, send, length);
//	S2F_ReceiverAppendData(receiver, data, sendLength);
//	recLength = S2F_ReceiverParse(receiver, rec, 512);
//	logStr('g', data2Str(rec, recLength));
//
//	return recLength;
//}
//
//int simulator::sim2(int count, int length, int sendRate)
//{
//	unsigned char** input = new unsigned char*[count];
//	int* inputLength = new int[count];
//	unsigned char** output = new unsigned char*[count];
//	int* outputLength = new int[count];
//	for (int i = 0; i < count; ++i)
//	{
//		input[i] = new unsigned char[length];
//		output[i] = new unsigned char[length];
//	}
//	for (int i = 0; i < count; ++i)
//	{
//		inputLength[i] = rand() % (length / 3);
//		for (int j = 0; j < inputLength[i]; ++j)
//		{
//			input[i][j] = rand() % 256;
//		}
//	}
//
//	int sendNum = 0;
//	int recNum = 0;
//	unsigned char* stream;
//	int streamLength;
//	while (sendNum < count)
//	{
//		if (0 != rand() % sendRate)
//		{
//			streamLength = S2F_SenderGenFrame(sender, input[sendNum], inputLength[sendNum]);
//			S2F_ReceiverAppendData(receiver, stream, streamLength);
//			++sendNum;
//		}
//		else
//		{
//			do
//			{
//				cout << recNum << " ";
//				streamLength = S2F_ReceiverParse(receiver, output[recNum], length);
//				if (streamLength >= 0)
//				{
//					outputLength[recNum] = streamLength;
//					++recNum;
//				}
//			} while (streamLength >= 0);
//		}
//	}
//	do
//	{
//		streamLength = S2F_ReceiverParse(receiver, output[recNum], count);
//		if (streamLength >= 0)
//		{
//			outputLength[recNum] = streamLength;
//			++recNum;
//		}
//	} while (streamLength >= 0);
//
//
//	for (int i = 0; i < count; ++i)
//	{
//		delete input[i];
//		delete output[i];
//	}
//	delete input;
//	delete inputLength;
//	delete output;
//	delete outputLength;
//
//	return recNum;
//}
//
//
//void simulator::sim3(int count, int maxLength, int sendSpeed)
//{
//	int sendCount = 0, recCount = 0;
//	int length;
//	unsigned char* cacheBuffer = new unsigned char[maxLength];
//	unsigned char* afterLostBuffer = new unsigned char[maxLength];
//	unsigned char* outputBuffer = new unsigned char[maxLength * 5];
//
//	int errorcount = 0, fullcount = 0;
//
//
//	while (sendCount < count)
//	{
//		if (0 < rand() % (sendSpeed + 1))
//		{
//			length = rand() % maxLength;
//			for (int i = 0; i < length; ++i)
//			{
//				cacheBuffer[i] = rand() % 256;
//			}
//			S2F_SenderGenFrame(sender, cacheBuffer, length);
//			logStr('r', int2Str(sendCount) + ":" + data2Str(cacheBuffer, length));
//
//			int lostIndex = 0;
//			for (int i = 0; i < sender->dataLength; ++i)
//			{
//				if (0 != rand() % 1000)
//				{
//					afterLostBuffer[lostIndex] = sender->buffer.data[i];
//					++lostIndex;
//				}
//				else
//				{
//					logStr('b', "lost:" + int2Str(lostIndex) + " " + int2Str(sender->buffer.data[i]));
//				}
//			}
//
//			S2F_ReceiverAppendData(receiver, afterLostBuffer, lostIndex);
//
//			++sendCount;
//		}
//		else
//		{
//			while (true)
//			{
//				int recLength;
//				while (true)
//				{
//					recLength = S2F_ReceiverParse(receiver, outputBuffer, maxLength * 5);
//					if (-3 == recLength)
//					{
//						logStr('m', "error");
//						errorcount++;
//						++recCount;
//						continue;
//					}
//					else
//					{
//						break;
//					}
//				}
//				if (0 <= recLength)
//				{
//					logStr('y', int2Str(recCount) + ":" + data2Str(outputBuffer, recLength));
//					++recCount;
//				}
//				else if (-1 == recLength)
//				{
//					break;
//				}
//				else if (-2 == recLength)
//				{
//					break;
//				}
//				else if (-4 == recLength)
//				{
//					S2F_ReceiverClean(receiver);
//					logStr('m', "full");
//					fullcount++;
//					++recCount;
//				}
//			}
//		}
//	}
//	while (true)
//	{
//		int recLength;
//		while (true)
//		{
//			recLength = S2F_ReceiverParse(receiver, outputBuffer, maxLength * 5);
//			if (-3 == recLength)
//			{
//				logStr('m', "error");
//				errorcount++;
//				++recCount;
//				continue;
//			}
//			else
//			{
//				break;
//			}
//		}
//		if (0 <= recLength)
//		{
//			logStr('y', int2Str(recCount) + ":" + data2Str(outputBuffer, recLength));
//			++recCount;
//		}
//		else if (-1 == recLength)
//		{
//			break;
//		}
//		else if (-2 == recLength)
//		{
//			break;
//		}
//		else if (-4 == recLength)
//		{
//			S2F_ReceiverClean(receiver);
//			fullcount++;
//			logStr('m', "full");
//			++recCount;
//		}
//	}
//
//	logStr('w', "");
//	cout << "error:" << errorcount << endl << "fullcount:" << fullcount << endl << "sendCount:" << sendCount << endl << "recCount:" << recCount;
//}
//
//
//void simulator::sim4(int count, int maxLength)
//{
//	vector<unsigned char> data;
//	unsigned char *temp = new unsigned char[2 * (long)maxLength];
//	int length;
//	int index = 0;
//
//	ofstream input, output;
//
//	input.open("./input.txt", ios::ate);
//	for (int i = 0; i < count; ++i)
//	{
//		length = rand() % maxLength;
//		for (int i = 0; i < length; ++i)
//		{
//			unsigned char byte = rand() % 256;
//			temp[i] = byte;
//			string str = int2Str(byte);
//			input.write(str.c_str(), str.size());
//		}
//		input.write("\n", 1);
//		S2F_SenderGenFrame(sender, temp, length);
//		for (int i = 0; i < sender->dataLength; ++i)
//		{
//			data.push_back(sender->buffer.data[i]);
//		}
//	}
//	input.close();
//
//	output.open("./output.txt", ios::ate);
//	int dataLength = data.size();
//	index = 0;
//	while (index < dataLength)
//	{
//		length = rand() % maxLength;
//		length = dataLength- index >= length ? length : dataLength - index;
//		S2F_ReceiverAppendData(receiver, data.data() + index, length);
//		int frameSize = S2F_ReceiverParse(receiver, temp, 2 * maxLength);
//		if (frameSize >= 0)
//		{
//
//		}
//		index += length;
//	}
//
//	delete[] temp;
//}



void simulator::logStr(char color, string str)
{
	switch (color)
	{
	case 'r':	cout << "\033[31m" << str;	break;
	case 'g':	cout << "\033[32m" << str;	break;
	case 'y':	cout << "\033[33m" << str;	break;
	case 'b':	cout << "\033[34m" << str;	break;
	case 'm':	cout << "\033[35m" << str;	break;
	case 'c':	cout << "\033[36m" << str;	break;
	case 'w':	cout << "\033[37m" << str;	break;
	default:	cout << "\033[37m" << str;	break;
	}
	cout << endl;
}


string simulator::int2Str(int num)
{
	ostringstream stream;
	stream << num;
	return stream.str();
}

string simulator::data2Str(unsigned char* data, int length)
{
	ostringstream stream;

	for (int i = 0; i < length; ++i)
	{
		stream << hex << (int)data[i] << " ";
	}
	return stream.str();
}

vector<unsigned char> simulator::genData(int size) {
	vector<unsigned char> data;
	for (int i = 0; i < size; ++i) {
		data.push_back(rand() % 256);
	}
	return data;
}
